package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.ConfigConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaySheetTypeEnum;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.InvoiceErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.InvoiceConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.PayPlanEntityExt;
import com.xbongbong.saas.domain.entity.ext.PayPlanSheetEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseInvoiceEntityExt;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.SheetAloneEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.PayPlanEnum;
import com.xbongbong.saas.enums.business.PayRelationshipEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PurchaseInvoiceEnum;
import com.xbongbong.saas.enums.dictionary.PayPlanStatusEnum;
import com.xbongbong.saas.help.AnalyticalHelp;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.help.InvoiceCommonHelp;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.help.SaasPurchaseInvoiceHelp;
import com.xbongbong.saas.help.SaveFormatHelp;
import com.xbongbong.saas.model.PayPlanModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PurchaseInvoiceModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.util.InvoiceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;

/**
 * @author 吴峰
 * @date 2021/07/15 17:15
 */
@Service("purchaseInvoiceAnalyticalServiceImpl")
public class PurchaseInvoiceValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {

    private static final Logger LOGGER = LoggerFactory.getLogger(PurchaseInvoiceValidateAnalyticalServiceImpl.class);
    
    @Resource
    private UserModel userModel;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private PayPlanModel payPlanModel;
    @Resource
    private PayPlanSheetModel payPlanSheetModel;
    @Resource
    private PurchaseInvoiceModel purchaseInvoiceModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private SaasPurchaseInvoiceHelp saasPurchaseInvoiceHelp;
    @Resource
    private AnalyticalHelp analyticalHelp;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        try {
            boolean isNew = analyticalHelp.isNew(validateDataDTO.getDataId(), validateDataDTO.getTaskId(), validateDataDTO.getCorpid());
            JSONObject data= validateDataDTO.getData();
            Integer isImport = validateDataDTO.getIsImport();
            Integer isCover = validateDataDTO.getIsCover();
            //是覆盖导入作废的发票。直接在文档中提示错误信息
            //判断当前发票是否作废
            Integer isCancel = FastJsonHelper.getIntegerOrDefaultFromFormData(data, PurchaseInvoiceEnum.IS_CANCEL.getAttr(), BasicConstant.ZERO);
            if (Objects.equals(BasicConstant.ONE, isCancel)){
                //是作废的发票，提示作废发票不允许编辑
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.INVOICE_CANCEL_NOT_EDIT);
            }
            //是覆盖导入作废的发票
            boolean invoiceFlag = Objects.equals(BasicConstant.ONE, isCover) && Objects.equals(BasicConstant.ONE, isCancel);
            if (invoiceFlag){
                throw new XbbException(ImportErrorCodeEnum.API_ERROR_235058);
            }
            JSONArray amountDetail = validateDataDTO.getAmountDetail();
            Boolean isPrePaySheet = false;
            Boolean isPrePaySheetUnion = false;
            String corpid = validateDataDTO.getCorpid();
            SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojoOld = validateDataDTO.getSaasNeedRedundantAttrPoJo();
            if (saasNeedRedundantAttrPojoOld != null && saasNeedRedundantAttrPojoOld.getReturnedPurchaseId() != null) {
                data.put(PaasConstant.RETURNED_PURCHASE_ID, saasNeedRedundantAttrPojoOld.getReturnedPurchaseId());
            }
            if(Objects.equals(isImport,BasicConstant.ONE)){
                //导入有些炒作进行处理
                verifyImportData(data,validateDataDTO.getCorpid(),isPrePaySheet);
            }
            Long purchaseInvoiceId = 0L;
            if(Objects.nonNull(validateDataDTO.getDataId()) && !isNew){
                purchaseInvoiceId = validateDataDTO.getDataId();
            }
            JSONArray applyUser = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,PurchaseInvoiceEnum.APPLY_USER.getAttr(),null);
            if(CollectionsUtil.isEmpty(applyUser) && !Objects.equals(isImport,BasicConstant.ONE)){
                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217023);
            }
            //进项发票对离职人员进行过滤
            if (CollectionsUtil.isNotEmpty(applyUser) && !Objects.equals(isImport,BasicConstant.ONE)) {
                String userIdIn = applyUser.getString(0);
                if (userIdIn != null && userIdIn.length() > 0) {
                    UserEntity userEntity = userModel.getByKey(userIdIn, corpid);
                    if (Objects.isNull(userEntity)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100065);
                    }
                }
            }
            JSONArray supplierArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, PurchaseInvoiceEnum.SUPPLIER_NAME.getAttr(),new JSONArray());
            JSONArray purchaseArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,PurchaseInvoiceEnum.PURCHASE_ID.getAttr(),new JSONArray());
            JSONArray payPlanArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr(),new JSONArray());
            JSONArray paySheetArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(data,PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr(),new JSONArray());

            List<Long> supplierIds = new ArrayList<>();
            List<Long> purchaseIds = new ArrayList<>();
            List<Long> payPlanIds = new ArrayList<>();
            List<Long> paySheetIds = new ArrayList<>();

            if(Objects.nonNull(supplierArray)){
                getRefIds(supplierArray,supplierIds);
                if(Objects.equals(supplierArray.size(),BasicConstant.ZERO)){
                    data.put(PurchaseInvoiceEnum.SUPPLIER_NAME.getAttr(),null);
                }
            }
            if (Objects.nonNull(purchaseArray) && purchaseArray.size()>0) {
                getRefIds(purchaseArray,purchaseIds);
            }else {
                if(purchaseInvoiceId>0L){
                    data.put(PurchaseInvoiceEnum.PURCHASE_ID.getAttr(),null);
                    data.put(PurchaseInvoiceEnum.PURCHASE_ID_LINK_TEXT.getAttr(),null);
                }
            }
            if(Objects.nonNull(payPlanArray) && payPlanArray.size()>0){
                getRefIds(payPlanArray,payPlanIds);
            }else {
                if(purchaseInvoiceId>0L){
                    data.put(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr(),null);
                    data.put(PurchaseInvoiceEnum.PAY_PLAN_ID_LINK_TEXT.getAttr(),null);
                }
            }
            if(Objects.nonNull(paySheetArray) && paySheetArray.size()>0){
                getRefIds(paySheetArray,paySheetIds);
            }else {
                if(purchaseInvoiceId > 0L){
                    data.put(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr(),null);
                    data.put(PurchaseInvoiceEnum.PAY_SHEET_ID_LINK_TEXT.getAttr(),null);
                }
            }
            if(!Objects.equals(isImport,BasicConstant.ONE)){
                isPrePaySheet = parsePrePaySheet(data);
                if(isPrePaySheet && paySheetArray.size()>= BasicConstant.TWO){
                    isPrePaySheetUnion = true;
                    isPrePaySheet = true;
                }
            }
            boolean flag = Objects.equals(validateDataDTO.getIsImport(), BasicConstant.ONE) && (isPrePaySheet || isPrePaySheetUnion);
            if(flag){
                //如果导入预收款付款单
                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217012);
            }
            //是否需要 退货退款校验
            //现在已经剔除了开票金额为0的关联单据 这一步 不需要 关联单据可开票为0判断
            formatPurchaseInvoiceLinkBusiness4Save(data);

            SaveFormatHelp.formatLinkBusiness4SaveByArray(data,PurchaseInvoiceEnum.ORIGIN_ID.getAttr(),PurchaseInvoiceEnum.ORIGIN_ID_LINK_TEXT.getAttr(),PurchaseInvoiceEnum.ORIGIN_ID.getFieldType());
            Long originId = FastJsonHelper.getLongOrDefaultFromFormData(data,PurchaseInvoiceEnum.ORIGIN_ID.getAttr(),0L);
            Long supplierId = FastJsonHelper.getLongFromFormData(data,PurchaseInvoiceEnum.SUPPLIER_NAME.getAttr());
            Long editPurchaseInvoiceId = null;
            if(purchaseInvoiceId > 0){
                editPurchaseInvoiceId = purchaseInvoiceId;
            }
            InvoiceCommonHelp.getMinusAmountFormRedInvoice(data,amountDetail,originId,isImport,validateDataDTO.getBusinessType());
            Double totalMoney = getDoubleOrDefaultFromFormData(data,PurchaseInvoiceEnum.TOTAL_MONEY.getAttr(),0.0D);
            verifyPurchaseInvoiceMoney(data,originId,corpid,totalMoney,editPurchaseInvoiceId);
            // 是否合同合并开票
            boolean  isPurchaseUnion = false;
            // 是否付款合并开票
            boolean isPayPlanUnion = false;
            //是选择了合同
            boolean isHasPurchase = false;
            //是否选择了付款计划
            boolean isHasPayPlan = false;
            //是否选择了回款单
            boolean isHashPaySheet = false;
            //是否回款单合并开票
            boolean isPaySheetUnion = false;
            if(Objects.nonNull(supplierId) && Objects.nonNull(purchaseArray) && purchaseArray.size()>0){
                isHasPurchase = true;
                if(purchaseArray.size()>BasicConstant.ONE){
                    isPurchaseUnion = true;
                }
                if(Objects.nonNull(payPlanArray) && payPlanArray.size() >BasicConstant.ZERO){
                    isHasPayPlan = true;
                    if(payPlanArray.size() > BasicConstant.ONE){
                        isPurchaseUnion = false;
                        isPayPlanUnion = true;
                    }
                }
                if(paySheetArray.size() > BasicConstant.ZERO){
                    isHashPaySheet = true;
                    if(paySheetArray.size() > BasicConstant.ONE){
                        isPurchaseUnion = false;
                        isPaySheetUnion = true;
                    }
                }
            }else if(Objects.nonNull(supplierId)){
                if(paySheetArray.size() > BasicConstant.ZERO){
                    isHashPaySheet = true;
                    if(paySheetArray.size() > BasicConstant.ONE){
                        isPaySheetUnion = true;
                        if(isPrePaySheet){
                            isPaySheetUnion = false;
                            isPrePaySheetUnion = true;
                        }
                    }
                }
            }
            SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo = new SaasNeedRedundantAttrPojo();
            saasNeedRedundantAttrPojo.setHasPurchase(isHasPurchase);
            saasNeedRedundantAttrPojo.setHasPayPlan(isHasPayPlan);
            saasNeedRedundantAttrPojo.setHasPaySheet(isHashPaySheet);
            saasNeedRedundantAttrPojo.setPurchaseUnion(isPurchaseUnion);
            saasNeedRedundantAttrPojo.setPayPlanUnion(isPayPlanUnion);
            saasNeedRedundantAttrPojo.setPaySheetUnion(isPaySheetUnion);
            saasNeedRedundantAttrPojo.setPrePaySheet(isPrePaySheet);
            saasNeedRedundantAttrPojo.setPrePaySheetUnion(isPrePaySheetUnion);
            boolean hasPurchaseOrPay = (isHasPayPlan || isHashPaySheet || isHasPurchase) && originId == 0L;

            if(hasPurchaseOrPay){
                List<Long> refIds = null;
                if(isHasPayPlan){
                    refIds = payPlanIds;
                }
                if(isHashPaySheet){
                    refIds = paySheetIds;
                }
                Map<String,Object> relationMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                relationMap.put("purchaseNum",purchaseIds.size());
                relationMap.put("payPlanNum",payPlanIds.size());
                relationMap.put("paySheetNum",paySheetIds.size());
                if(!Objects.equals(isImport,BasicConstant.ONE)){
                    InvoiceUtil.verifyUnionInvoiceMoney(saasNeedRedundantAttrPojo,relationMap,amountDetail,data,originId,purchaseIds,refIds,XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
                }
                relationMap = saasPurchaseInvoiceHelp.getRelationMapForJudgeMoney(isHashPaySheet,isPrePaySheet,isPrePaySheetUnion,isHasPayPlan,corpid,purchaseIds,refIds);
                // 审批、新建、编辑、还原 金额判断
                saasPurchaseInvoiceHelp.invoiceAmountJudgment(corpid,purchaseInvoiceId,totalMoney,relationMap,isImport,isCover,BasicConstant.ZERO,amountDetail);
            }
            if(originId > 0L && !Objects.equals(isImport,BasicConstant.ONE)){
                List<Long> refIds = null;
                if(isHasPayPlan){
                    refIds = payPlanIds;
                }
                if(isHashPaySheet){
                    refIds = paySheetIds;
                }
                Map<String,Object> relationMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                relationMap.put("purchaseNum",purchaseIds.size());
                relationMap.put("payPlanNum",payPlanIds.size());
                relationMap.put("paySheetNum",paySheetIds.size());
                InvoiceUtil.verifyUnionInvoiceMoney(saasNeedRedundantAttrPojo,relationMap,amountDetail,data,originId,purchaseIds,refIds,XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
            }
            for (Map.Entry<String,Object> entry : SaasDataInitHelp.initPurchaseInvoice().entrySet()){
                SaasDataInitHelp.antDataSet(data,entry.getKey(),entry.getValue());
            }
            if (CollectionsUtil.isNotEmpty(amountDetail)) {
                saasNeedRedundantAttrPojo.setAmountDetail(amountDetail);
            }
            validateDataDTO.setData(data);
            validateDataDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPojo);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("purchaseInvoiceAnalyticalServiceImpl.beforeSave error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    /**
     * 进项发票导入效验
     * @param data
     * @param corpid
     * @param isPrePaySheet
     * @throws XbbException
     */
    public void verifyImportData(JSONObject data,String corpid,Boolean isPrePaySheet) throws XbbException{
        if(Objects.nonNull(data)){
            if(Objects.isNull(data.getString(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr()))){
                //当付款计划或者付款单任意存在一个的时候  类型必填（产品讨论结果）
                if(CollectionsUtil.isNotEmpty(data.getJSONArray(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr())) || CollectionsUtil.isNotEmpty(data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()))){
                    throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217018);
                }
                if(CollectionsUtil.isNotEmpty(data.getJSONArray(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr()))){
                    data.put(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr(),PayRelationshipEnum.PAY_PLAN.getCode());
                }
                if(CollectionsUtil.isNotEmpty(data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()))) {
                    data.put(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr(),PayRelationshipEnum.PAY_SHEET.getCode());
                }
            }
            //三者都在的时候不再给默认值，以回款类型为标准  （产品讨论结果）2020年1月10日15:42:45
            if(Objects.nonNull(data.getString(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr()))){
                if(Objects.equals(PayRelationshipEnum.PAY_PLAN.getCode(),data.getString(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr()))){
                    data.remove(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr());
                }else if(Objects.equals(PayRelationshipEnum.PAY_SHEET.getCode(),data.getString(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr()))){
                    data.remove(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr());
                }
            }

            if(Objects.isNull(data.getJSONArray(PurchaseInvoiceEnum.PURCHASE_ID.getAttr()))){
                if(Objects.nonNull(data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()))){
                    isPrePaySheet = true;
                }
                if(Objects.nonNull(data.getJSONArray(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr()))){
                    throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217019);
                }
            }
            if(Objects.equals(data.getString(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr()),PayRelationshipEnum.PAY_PLAN.getCode()) && Objects.nonNull(data.getJSONArray(PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr()))) {
                JSONArray dataArray = data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr());
                Set<Long> idSet = new HashSet<>();
                Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if(CollectionsUtil.isNotEmpty(dataArray)) {
                    for (int i = 0; i < dataArray.size(); i++) {
                        JSONObject dataObject = dataArray.getJSONObject(i);
                        if (Objects.nonNull(dataObject)) {
                            idSet.add(dataObject.getLong(BasicConstant.ID));
                        }
                    }
                    param.put("corpid",corpid);
                    param.put("idIn",idSet);
                    param.put("del",BasicConstant.ZERO);
                    List<PayPlanEntityExt> payPlanEntityExtList = payPlanModel.findEntitys(param);
                    if(CollectionsUtil.isNotEmpty(payPlanEntityExtList)) {
                        for (PayPlanEntityExt payPlanEntityExt : payPlanEntityExtList) {
                            String status = FastJsonHelper.getStringOrDefaultFromFormData(payPlanEntityExt.getData(), PayPlanEnum.STATUS.getAttr(), PayPlanStatusEnum.UN_RECEIVABLES.getCode());
                            boolean isBad = Objects.equals(status, PayPlanStatusEnum.BAD_DEBT.getCode()) || Objects.equals(status, PayPlanStatusEnum.PARTIAL_BAD_DEBT.getCode());
                            if (isBad) {
                                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_216017);
                            }
                        }
                    }
                }
            }
            if(Objects.equals(data.getString(PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr()),PayRelationshipEnum.PAY_SHEET.getCode()) && Objects.nonNull(data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()))){
                JSONArray dataArray = data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr());
                Set<Long> idSet = new HashSet<>();
                Set<String> uuids = new HashSet<>();
                JSONArray totalArray = new JSONArray();
                Map<String,JSONArray> paySheetMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Long,String> uuidMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if(CollectionsUtil.isNotEmpty(dataArray)) {
                    for (int i=0;i < dataArray.size(); i++) {
                        JSONObject dataObject = dataArray.getJSONObject(i);
                        if(Objects.nonNull(dataObject)){
                            idSet.add(dataObject.getLong(BasicConstant.ID));
                        }
                    }
                    param.put("corpid",corpid);
                    param.put("idIn",idSet);
                    param.put("del",BasicConstant.ZERO);
                    List<PayPlanSheetEntityExt> paySheetEntityExtList = payPlanSheetModel.findEntitys(param);
                    if(CollectionsUtil.isNotEmpty(paySheetEntityExtList)) {
                        for (PayPlanSheetEntityExt paySheetEntityExt : paySheetEntityExtList) {
                            if (Objects.nonNull(paySheetEntityExt.getUuid())) {
                                uuids.add(paySheetEntityExt.getUuid());
                                uuidMap.put(paySheetEntityExt.getId(), paySheetEntityExt.getUuid());
                            }
                            if (Objects.equals(paySheetEntityExt.getAlone(), SheetAloneEnum.CHILD.getCode())) {
                                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217020);
                            }
                            String status = FastJsonHelper.getStringOrDefaultFromFormData(paySheetEntityExt.getData(), PaySheetEnum.PAY_SHEET_TYPE.getAttr(), PaySheetTypeEnum.WRITE_OFF_PAY.getCode());
                            boolean isBadType = PaySheetTypeEnum.isBad(status);
                            boolean isRedType = PaySheetTypeEnum.isRed(status);
                            boolean isWriteOffPrePaySheet= Objects.equals(status,PaySheetTypeEnum.WRITE_OFF_PREPAY.getCode());
                            if(isBadType || isRedType){
                                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_216017);
                            }
                            if(isWriteOffPrePaySheet){
                                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217024);
                            }
                        }
                    }
                    List<PaasFormDataEntityExt> paySheetEntityExts = fundHelp.getChildEsDataListByParentUuids(XbbRefTypeEnum.PAY_SHEET, corpid,uuids,null,null);
                    paySheetEntityExts.forEach(paySheetEntityExt -> {
                        if(Objects.nonNull(paySheetEntityExts)) {
                            if(paySheetMap.containsKey(paySheetEntityExt.getUuid())) {
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put(BasicConstant.ID,paySheetEntityExt.getId());
                                jsonObject.put(BasicConstant.NAME,paySheetEntityExt.getSerialNo());
                                paySheetMap.get(paySheetEntityExt.getUuid()).add(jsonObject);
                            }else {
                                JSONObject jsonObject = new JSONObject();
                                jsonObject.put(BasicConstant.ID,paySheetEntityExt.getId());
                                jsonObject.put(BasicConstant.NAME,paySheetEntityExt.getSerialNo());
                                JSONArray paymentSheetArray = new JSONArray();
                                paymentSheetArray.add(jsonObject);
                                paySheetMap.put(paySheetEntityExt.getUuid(),paymentSheetArray);
                            }
                        }
                    });
                    for (int i=0;i < dataArray.size(); i++) {
                        JSONObject dataObject = dataArray.getJSONObject(i);
                        if(Objects.nonNull(dataObject)){
                            Long id = dataObject.getLong(BasicConstant.ID);
                            String uuid = uuidMap.get(id);
                            if(Objects.nonNull(paySheetMap.get(uuid))){
                                totalArray.addAll(paySheetMap.get(uuid));
                            }else {
                                totalArray.add(dataObject);
                            }
                        }
                    }
                    dataArray.clear();
                    dataArray.addAll(totalArray);
                    data.put(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr(),dataArray);
                }
            }
        }
    }

    private void formatPurchaseInvoiceLinkBusiness4Save(JSONObject data) throws XbbException{
        SaveFormatHelp.formatLinkBusiness4SaveByArray(data,PurchaseInvoiceEnum.SUPPLIER_NAME.getAttr(),PurchaseInvoiceEnum.SUPPLIER_NAME_LINK_TEXT.getAttr(),PurchaseInvoiceEnum.SUPPLIER_NAME.getFieldType());
        SaveFormatHelp.formatLinkBusiness4SaveByArray(data,PurchaseInvoiceEnum.PURCHASE_ID.getAttr(), PurchaseInvoiceEnum.PURCHASE_ID_LINK_TEXT.getAttr(), PurchaseInvoiceEnum.PURCHASE_ID.getFieldType());
        SaveFormatHelp.formatLinkBusiness4SaveByArray(data,PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr(), PurchaseInvoiceEnum.PAY_PLAN_ID_LINK_TEXT.getAttr(), PurchaseInvoiceEnum.PAY_PLAN_ID.getFieldType());
        SaveFormatHelp.formatLinkBusiness4SaveByArray(data,PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr(),PurchaseInvoiceEnum.PAY_SHEET_ID_LINK_TEXT.getAttr(),PurchaseInvoiceEnum.PAY_SHEET_ID.getFieldType());
    }
    
    private void getRefIds(JSONArray refIds,List<Long> ids){
        if(Objects.nonNull(refIds)){
            refIds.forEach((obj) ->{
                JSONObject refObjson = (JSONObject) obj;
                Long id = refObjson.getLong(StringConstant.SAAS_LINK_BUSINESS_ID) == null ? 0L : refObjson.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                ids.add(id);
            });
        }
    }

    private Boolean parsePrePaySheet(JSONObject data){
        if(Objects.nonNull(data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()))) {
            if(data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()).size() >0) {
                JSONObject paySheetObject = data.getJSONArray(PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()).getJSONObject(0);
                String paySheetType = paySheetObject.getString(InvoiceConstant.PAY_SHEET_TYPE);
                if (Objects.equals(paySheetType, PaySheetTypeEnum.PREPAY.getCode())) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * 校验开票金额
     *
     * @param originId        原始id
     * @param corpid          公司id
     * @param totalMoney      开票金额
     * @throws XbbException 校验异常
     * @author yuqian
     * @date 2020/2/26 14:57
     */
    private void verifyPurchaseInvoiceMoney(JSONObject data,Long originId,String corpid,Double totalMoney,Long editPurchaseInvoiceId) throws XbbException{
        if(Objects.equals(Math.abs(totalMoney),BasicConstant.ZERO_DOUBLE)){
            throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217001);
        }
        PurchaseInvoiceEntityExt originPurchaseInvoice;
        if(originId > 0){
            if(totalMoney > BasicConstant.ZERO_DOUBLE){
                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_217002);
            }
            originPurchaseInvoice = purchaseInvoiceModel.getByKey(originId,corpid);
            if(originPurchaseInvoice == null){
                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_216011);
            }
            double redTotalMoney = 0D;
            if(Objects.nonNull(editPurchaseInvoiceId)){
                redTotalMoney = getRedTotalMoneyByEdit(originId,corpid,editPurchaseInvoiceId);
            }else {
                redTotalMoney = purchaseInvoiceModel.getRedTotalMoney(originId,corpid);
            }
            Double originTotalMoney = getDoubleFromFormData(originPurchaseInvoice.getData(),PurchaseInvoiceEnum.TOTAL_MONEY.getAttr());
            if(Arith.sub(Math.abs(redTotalMoney + totalMoney),originTotalMoney) > ConfigConstant.amountAccuracy){
                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_216013);
            }
        }else {
            if(totalMoney < BasicConstant.ZERO_DOUBLE){
                throw new XbbException(InvoiceErrorCodeEnum.API_ERROR_216020);
            }
        }
    }

    /**
     * 编辑 时 获取红冲金额
     * @param originId
     * @param corpid
     * @param editInvoiceId
     * @return
     * @throws XbbException
     */
    private Double getRedTotalMoneyByEdit(Long originId, String corpid,Long editInvoiceId) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<PaasFormDataEntityExt> paasFormDataEntityExts = paasEsModel.selectByOneCondition(RedundantTemplateTypeEnum.PURCHASE_INVOICE.getCode(),PurchaseInvoiceEnum.ORIGIN_ID.getAttr(), originId, param, IndexTypeEnum.IDX_SAAS_PURCHASE_INVOICE);
        Double redTotalMoney = 0D;
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExts) {
            if(Objects.equals(editInvoiceId,paasFormDataEntityExt.getId())){
                continue;
            }
            Double money = FastJsonHelper.getDoubleFromFormData(paasFormDataEntityExt.getData(), PurchaseInvoiceEnum.TOTAL_MONEY.getAttr());
            if (money == null) {
                money = 0D;
            }
            redTotalMoney += money;
        }
        return redTotalMoney;
    }


}
